﻿/******************************************************************************
	Cobalt - utility libraries for building XNA games
	Copyright (C) 2008 Philip Djonov

	This program is free software; you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2 of the License, or (at your option)
	any later version.

	This program is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
	for more details.

	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the
	
		Free Software Foundation, Inc.
		51 Franklin Street, Fifth Floor
		Boston, MA  02110-1301, USA.
******************************************************************************/

using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Cobalt.Framework.Graphics
{

	public sealed class SpriteSheet
	{
		internal Texture2D[] sheetImages;

		internal struct SpriteDesc
		{
			public string Name;
			public int SheetIndex;
			public Rectangle SourceRectangle;
		}

		internal SpriteDesc[] sprites;

		public int GetSpriteIndex( string name )
		{
			if( name == null )
				throw new ArgumentNullException();

			//inlined binary search since other methods generate garbage

			int min = 0;
			int max = sprites.Length - 1;

			while( min <= max )
			{
				int mid = min + (max - min) / 2;
				int cmp = string.CompareOrdinal( sprites[mid].Name, name );

				if( cmp == 0 )
					return mid;

				if( cmp < 0 )
					min = mid + 1;
				else
					max = mid - 1;
			}

			return -1; 
		}

		public int Count { get { return sprites.Length; } }

		public void GetSpriteInfo( int index, out Texture2D texture, out Rectangle rect )
		{
			if( index < 0 || index >= sprites.Length )
				throw new ArgumentOutOfRangeException();

			texture = sheetImages[sprites[index].SheetIndex];
			rect = sprites[index].SourceRectangle;
		}

		public void GetSpriteInfo( string name, out Texture2D texture, out Rectangle rect )
		{
			int index = GetSpriteIndex( name );

			if( index < 0 )
				throw new KeyNotFoundException();

			texture = sheetImages[sprites[index].SheetIndex];
			rect = sprites[index].SourceRectangle;			
		}
	}

	public static class SpriteSheetHelpers
	{
		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, int spriteIndex, Rectangle destinationRectangle, Color color )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteIndex, out tex, out sourceRect );

			batch.Draw( tex, destinationRectangle, sourceRect, color );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, int spriteIndex, Vector2 position, Color color )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteIndex, out tex, out sourceRect );

			batch.Draw( tex, position, sourceRect, color );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, int spriteIndex, Rectangle destinationRectangle, Color color,
			float rotation, Vector2 origin, SpriteEffects effects, float layerDepth )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteIndex, out tex, out sourceRect );

			batch.Draw( tex, destinationRectangle, sourceRect, color, rotation, origin, effects, layerDepth );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, int spriteIndex, Vector2 position, Color color, 
			float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteIndex, out tex, out sourceRect );

			batch.Draw( tex, position, sourceRect, color, rotation, origin, scale, effects, layerDepth );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, int spriteIndex, Vector2 position, Color color, 
			float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteIndex, out tex, out sourceRect );

			batch.Draw( tex, position, sourceRect, color, rotation, origin, scale, effects, layerDepth );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, string spriteName, Rectangle destinationRectangle, Color color )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteName, out tex, out sourceRect );

			batch.Draw( tex, destinationRectangle, sourceRect, color );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, string spriteName, Vector2 position, Color color )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteName, out tex, out sourceRect );

			batch.Draw( tex, position, sourceRect, color );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, string spriteName, Rectangle destinationRectangle, Color color,
			float rotation, Vector2 origin, SpriteEffects effects, float layerDepth )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteName, out tex, out sourceRect );

			batch.Draw( tex, destinationRectangle, sourceRect, color, rotation, origin, effects, layerDepth );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, string spriteName, Vector2 position, Color color,
			float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteName, out tex, out sourceRect );

			batch.Draw( tex, position, sourceRect, color, rotation, origin, scale, effects, layerDepth );
		}

		public static void Draw( this SpriteBatch batch, SpriteSheet sheet, string spriteName, Vector2 position, Color color,
			float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth )
		{
			Texture2D tex;
			Rectangle sourceRect;

			sheet.GetSpriteInfo( spriteName, out tex, out sourceRect );

			batch.Draw( tex, position, sourceRect, color, rotation, origin, scale, effects, layerDepth );
		}
	}

}